use std::fmt::Debug;
use std::marker::{PhantomData, PhantomPinned};
use std::ptr::addr_of;
use std::rc::Rc;

/// PhantomData的理解
/// 1. 标记所有权
/// 2. 申明类型，生命周期使用情况


/// 案例实现了一个比较复杂的Borrow Trait,要求实现此trait的类至少有'a的生命周期
trait RefTrait<'a, T: 'a + ?Sized> {
    fn as_ref_type(&'a self) -> &'a T;
}

/// RefModel要求可以获取实现RefTrait的变量的所有权
/// 提供暴露借用的方式获取对K的引用
struct RefModel<'a, K, T>
where
    K: 'a + ?Sized,
    T: RefTrait<'a, K>,
{
    ref_model: T,
    marker: PhantomData<&'a K>, // marker is must 这里可以表明'a ,K的使用范围和生命周期
}

impl<'a, K, T> RefModel<'a, K, T>
where
    K: ?Sized + Debug,
    T: RefTrait<'a, K>,
{
    pub fn new(ref_model: T) -> Self {
        Self {
            ref_model,
            marker: PhantomData,
        }
    }
    pub fn show(&'a self) {
        println!("{:?}", self.ref_model.as_ref_type());
    }

    pub fn borrow(&'a self) -> &'a K {
        self.ref_model.as_ref_type()
    }
}

struct WrapString(String);

impl RefTrait<'_, str> for WrapString {
    fn as_ref_type(& self) -> & str {
        self.0.as_str()
    }
}

#[test]
fn phantom_data_test() {
    let wrapStr = WrapString("asd".to_string());

    let model = RefModel::new(wrapStr);
    model.show();
    let x = model.borrow();

}
